﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
using System.Threading;
using NotifyIcon = System.Windows.Forms.NotifyIcon;
using ContextMenuStrip = System.Windows.Forms.ContextMenuStrip;
using MouseEventArgs = System.Windows.Forms.MouseEventArgs;
using ToolStripMenuItem = System.Windows.Forms.ToolStripMenuItem;
using System.Diagnostics;
using System.Management;


namespace BrtVol
{
    /// <summary>
    /// BrightnessVolume.xaml の相互作用ロジック
    /// </summary>
    public partial class BrightnessVolume : Window
    {
        private NotifyIcon _notifyIcon;
        List<int> _brightnessValueList;

        public BrightnessVolume()
        {

            if (checkRunning())
            {
                this.Hide();
                setNotifyIcon();

                InitializeComponent();
                
                

                _brightnessValueList = getBrightnessValueList();
                int max = _brightnessValueList.Count - 1;
                if (max < 0)
                {
                    max = 0;
                }
                view_Slider_Volume.Minimum = 0;
                view_Slider_Volume.Maximum = max;


                updateCurrentBrightness();
                setWatcher();

            
            }
        }




        private bool checkRunning()
        {
            bool createdNew;
            Mutex mutex = new Mutex(true, "BrtVol", out createdNew);
            if (createdNew == false)
            {
                Application.Current.Shutdown();
                return false;
            }

            mutex.ReleaseMutex();
            return true;
        }


        private void setNotifyIcon()
        {
            ShowInTaskbar = false;

            ToolStripMenuItem exitItem = new ToolStripMenuItem();
            exitItem.Text = "Exit";
            exitItem.Click += exitItemOnClick;

            ContextMenuStrip menuStrip = new ContextMenuStrip();
            menuStrip.Items.Add(exitItem);

            _notifyIcon = new NotifyIcon();
            _notifyIcon.Text = "Brightness";
            _notifyIcon.Icon = Properties.Resources.bright;  // http://www.flaticon.com/free-icon/bright-lightbulb_53591
            _notifyIcon.Visible = true;
            _notifyIcon.ContextMenuStrip = menuStrip;
            _notifyIcon.MouseClick += notifyIconOnMouseClick;
        }


        private void exitItemOnClick(object sender, EventArgs eventArgs)
        {
            try
            {
                if (_watcher != null)
                {
                    _watcher.Stop();
                    _watcher.Dispose();
                    _watcher = null;
                }

                _notifyIcon.Dispose();
                Application.Current.Shutdown();
            }
            catch (Exception)
            {
                // NOP
            }
        }


        private void notifyIconOnMouseClick(object sender, MouseEventArgs mouseEventArgs)
        {
            this.Visibility = Visibility.Visible;

            int margin = 5;
            this.Top = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height - (this.Height + margin);
            this.Left = System.Windows.Forms.Cursor.Position.X - ((this.Width / 2));

            updateCurrentBrightness();
        }


        private void updateCurrentBrightness()
        {
            int currentBrightness = getCurrentBrightness();
            updateDisplayValue(currentBrightness);

            view_Slider_Volume.Value = _brightnessValueList.IndexOf(currentBrightness);
        }



        ManagementEventWatcher _watcher;
        private void setWatcher()
        {
            try
            {
                string strScope = @"root\WMI";
                string strQuery = "select * from WmiMonitorBrightnessEvent";
                _watcher = new ManagementEventWatcher(strScope, strQuery);
                _watcher.EventArrived +=_watcher_EventArrived;

                _watcher.Start();
            }
            catch(ManagementException)
            {
                // NOP
            }
        }

        private void _watcher_EventArrived(object sender, EventArrivedEventArgs e)
        {
            int currentBrightness = getCurrentBrightness();
            Dispatcher.Invoke(new Action(() =>
            {
                view_Slider_Volume.ToolTip = currentBrightness;
                view_TextBlock_CurrentBrightness.Text = currentBrightness.ToString() + "%";
                view_Slider_Volume.Value = _brightnessValueList.IndexOf(currentBrightness);
            }));
        }
        

        

        private void view_Hyperlink_Setting_Click(object sender, RoutedEventArgs e)
        {
            Process.Start("powercfg.cpl");
        }


        private void view_Slider_Volume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            int currentValue = (int)view_Slider_Volume.Value;
            int newBrightness = _brightnessValueList[currentValue];
            updateDisplayValue(newBrightness);

            setBrightness(newBrightness);
        }


        private void updateDisplayValue(int brightnessValue)
        {
            view_Slider_Volume.ToolTip = brightnessValue;
            view_TextBlock_CurrentBrightness.Text = brightnessValue.ToString() + "%";

            _notifyIcon.Text = "Brightness: " + brightnessValue.ToString() + "%";
        }


        private void Window_Deactivated(object sender, EventArgs e)
        {
            this.Visibility = Visibility.Collapsed;
        }


        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            try
            {
                e.Cancel = true;
                this.Visibility = Visibility.Collapsed;
            }
            catch (Exception)
            {
                // NOP
            }
        }


        #region WMI
        private List<int> getBrightnessValueList()
        {
            List<int> brightnessValueList = new List<int>();
            try
            {
                string strScope = @"root\WMI";
                string strQuery = "select * from WmiMonitorBrightness";
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(strScope, strQuery);

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    if (queryObj["Level"] != null)
                    {
                        byte[] arrLevel = (byte[])(queryObj["Level"]);
                        foreach (byte arrValue in arrLevel)
                        {
                            brightnessValueList.Add(int.Parse(arrValue.ToString()));
                        }
                    }

                    break;
                }
            }
            catch (ManagementException)
            {
                // NOP
            }

            return brightnessValueList;
        }


        private int getCurrentBrightness()
        {
            int currentBrightness = 10;

            try
            {
                string strScope = @"root\WMI";
                string strQuery = "select * from WmiMonitorBrightness";
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(strScope, strQuery);

                foreach (ManagementObject queryObj in searcher.Get())
                {
                    currentBrightness = int.Parse(queryObj["CurrentBrightness"].ToString());

                    break;
                }
            }
            catch (ManagementException)
            {
                // NOP
            }
            
            return currentBrightness;
        }



        private void setBrightness(int brightness)
        {
            byte newBrightNess = byte.Parse(brightness.ToString());

            string strScope = @"root\WMI";
            string strPath = "WmiMonitorBrightnessMethods";
            ManagementClass managementClass = new ManagementClass(strScope, strPath, null);
            foreach (ManagementObject managementObject in managementClass.GetInstances())
            {
                managementObject.InvokeMethod("WmiSetBrightness", new Object[] { UInt32.MaxValue, brightness });
                break;
            }
        }

        #endregion  // WMI


    }
}
